///\file glapplication.cpp
///\brief
///Ce fichier contient toutes les implémentations pour le fonctionnement
///d'une application générique héritée
///\author Allan BLANCHARD
#include "glapplication.hh"
#include <sstream>

GLApplication* GLApplication::gla        = 0;
unsigned int   GLApplication::nbinstance = 0;

void GLApplication::pinit()      { GLApplication::gla->init();       }
void GLApplication::pdisplay()   { GLApplication::gla->display();    }
void GLApplication::pidle()      { GLApplication::gla->idle();       }
void GLApplication::pkeynormal(unsigned char key, int x, int y) { 
  GLApplication::gla->keynormal(key, x, y);  
}
void GLApplication::pkeyspecial(int key, int x, int y){ 
  GLApplication::gla->keyspecial(key, x, y); 
}
void GLApplication::pmouseclick(int b, int e, int x, int y){ 
  GLApplication::gla->mouseclick(b, e, x, y); 
}
void GLApplication::pmousemot(int x, int y){ 
  GLApplication::gla->mousemot(x, y);   
}

void GLApplication::preshape(int width, int height){
  gla->reshape(width, height);
}

void GLApplication::ppassivemousemot(int x, int y){
  gla->passivemousemotion(x,y);
}

void GLApplication::pexit(){
  gla->exit();
}

///\brief
///la fonction render effectue les actions suivantes :
///- init
///- set reshape func
///- set display func
///- set idle func
///- set keyboard func
///- set special func
///- set mouseclick func
///- set mousemotion func
///- set passivemousemotion func
///- start main loop
void GLApplication::render(){
  pinit();
  glutReshapeFunc      (preshape);
  glutDisplayFunc      (pdisplay);
  glutIdleFunc         (pidle);
  glutKeyboardFunc     (pkeynormal);
  glutSpecialFunc      (pkeyspecial);
  glutMouseFunc        (pmouseclick);
  glutMotionFunc       (pmousemot);
  atexit               (pexit);
  glutPassiveMotionFunc(ppassivemousemot);

  glutMainLoop();
}

void GLApplication::init(){
  glEnable(GL_DEPTH_TEST);
  reshape(w,h);

  glEnableClientState(GL_VERTEX_ARRAY);
  glEnableClientState(GL_INDEX_ARRAY);
  glEnableClientState(GL_NORMAL_ARRAY);
}

void GLApplication::reshape(int width, int height){
  w = width;
  h = height;

  glViewport(0, 0, (GLsizei)w, (GLsizei)h);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(70,static_cast<double>(w)/static_cast<double>(h),0.001,100);
  glMatrixMode(GL_MODELVIEW);
}

void GLApplication::framerate(void){
  static int frame=0,time,timebase=0;
  std::ostringstream oss;
  frame++;
  time=glutGet(GLUT_ELAPSED_TIME);
  if (time - timebase > 1000) {
    oss<<name<<" : "<<(frame*1000.0/(time-timebase));
    glutSetWindowTitle(oss.str().c_str());
    timebase = time;
    frame = 0;
  }
}
